﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Microsoft.Win32;
using ParanoidMike.CacheMyWork;
using ParanoidMike.CacheMyWork.CacheMyWork.Properties;

namespace ParanoidMike.CacheMyWork
{
    // Note: an idea I had to run this app in the background and write entries to RunOnce every few minutes - this really won't work:
    // http://www.microsoft.com/technet/technetmag/issues/2006/12/WindowsConfidential
    // "When you try to install a service pack or upgrade to a newer version of Windows, the setup wizard checks the RunOnce key. If it's not empty, you will get an error message that says, "Hey, you still have some unfinished program installation in progress. Please finish that before you try to upgrade the operating system.""

    /// Upon initialization, this Tool enumerates all processes, then removes those that don't have a visible Window and those not started by the current User.
    /// The Tool will then enumerate all files held open by the User's visible applications.
    /// The Tool presents a Dialog showing the User's applications as well as the documents held open by those applications.
    /// The Tool will note any applications (and documents) selected by the User, and write entries to the User's RunOnce registry key for each application (and/or document).
    public static class UserRegistryConfiguration
    {
        #region Variables

            internal const string HKCURUNONCE = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
            internal const string HKCUEXPLORER = "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";

            /// <summary>
            /// This collection lists all those apps that will be hidden from the user when the user is presented with the list of applications from which the user may choose to cache.
            /// </summary>
            /// <remarks>
            /// Each entry must be specified with the same spelling as is represented by process.ProcessName.
            /// </remarks>
            static internal Hashtable hiddenApps;

        #endregion
        
        #region Properties

            static internal bool displayNonVisibleWindowsValue;
            // This Property stores the state of the user configuration (from Tools, Options menu) to enable the display of non-visible Windows.
            public static bool DisplayNonVisibleWindows
            {
                get { return displayNonVisibleWindowsValue; }
                // TODO: 2010-04-04 I just added this Setter - does it need any additional Registry logic like the restoreExplorerWindows Property?
                set
                {
                    displayNonVisibleWindowsValue = value;
                }
            }

            private static bool restoreExplorerWindowsValue;
            // This Property stores the state of the user's configuration of Windows Explorer's setting to "restore previous folder windows at next logon"
            public static bool RestoreExplorerWindows
            {
                get { return restoreExplorerWindowsValue; }
                set
                {
                    restoreExplorerWindowsValue = value;
                    Registry.SetValue(HKCUEXPLORER, "PersistBrowsers", Convert.ToInt32(value));
                }
            }
            #endregion

        #region Public Methods

        /// <summary>
            /// Initialize the current user's configuration settings.
            /// </summary>
            /// <remarks></remarks>
        public static void GetAppConfig()
            {
                GetUserConfiguration();
            }

        /// <summary>
            /// Save the current user's configuration settings.
            /// </summary>
            /// <remarks></remarks>
        public static void SetAppConfig()
            {
                SetUserConfiguration();
            }

        /// <summary>
        /// Writes the submitted values to a new entry in the current user's HKCU RunOnce registry key, so that the submitted command line will be launched at next logon.
        /// </summary>
        public static void SetRunOnceValue(string valueName, string commandLine)
        {
            if (String.IsNullOrEmpty(valueName))
            {
                throw new ArgumentNullException("valueName");
            }

            if (String.IsNullOrEmpty(commandLine))
            {
                throw new ArgumentNullException("commandLine");
            }

            Registry.SetValue(HKCURUNONCE, valueName, commandLine);
        }

        #endregion
        
        #region Private Methods

            /// <summary>
            /// Read in user configuration from application settings.
            /// </summary>
            /// <remarks>
            /// Currently the application uses the user.config application settings file.
            /// </remarks>
            private static void GetUserConfiguration()
            {
                // The setting that enables the display of non-visible Windows apps in the Apps checklist will toggle the internal variable to match
                if (Settings.Default.DisplayNonvisibleWindows)
                {
                    displayNonVisibleWindowsValue = true;
                }

                else
                {
                    displayNonVisibleWindowsValue = false;
                }

                hiddenApps = new Hashtable();

                if (Settings.Default.HiddenApps != null)
                {
                    // Enumerate the strings from the hiddenApps setting (a Collection) that represent the default and/or user-selected apps that should be hidden from the checklist of potential apps to cache
                    foreach (string processName in Settings.Default.HiddenApps)
                    {
                        // 2009-11-15: Changed this variable to HashTable datatype, and for the moment I'm passing in processName as both needed parameters
                        hiddenApps.Add(processName, processName);
                    }                    
                }

                // Read in the user's Registry settings
                // This setting configures Windows Explorer to enable "restore folder windows at next logon"
                //    if (Registry.GetValue(HKCUEXPLORER, "PersistBrowsers", 0) == 1) // This is how the C# converter started out
                if (Registry.GetValue(HKCUEXPLORER, "PersistBrowsers", 0).ToString() == "1")
                {
                    RestoreExplorerWindows = true;
                }
                else
                {
                    RestoreExplorerWindows = false;
                }
            }

            /// <summary>
            /// Save the current membership of the hiddenApps collection to user settings.
            /// </summary>
            /// <remarks></remarks>
            private static void SetUserConfiguration()
            {
                System.Collections.Specialized.StringCollection previousHiddenApps;
                previousHiddenApps = new System.Collections.Specialized.StringCollection();

                // First cache the values last found in the user's hiddenApps settings in user.config
                foreach (string processName in Settings.Default.HiddenApps)
                {
                    previousHiddenApps.Add(processName);
                }

                // Next remove the current user settings
                Settings.Default.HiddenApps.Clear();

                foreach (string processName in hiddenApps)
                {
                    Settings.Default.HiddenApps.Add(processName);
                }

                Settings.Default.Save();

                // TODO: create logic to restore the previous settings if an unrecoverable error is encountered (including throwing an Exception that can be propagated to the user)
                // TODO: dispose of the temporary cache of previously hidden applications

            }
            #endregion
        }
}
